//-----------------------------------------------------------------------------
// <copyright file="PluginHost.cs" company="Justin Wallace Saunders">
//     Copyright (c) Microsoft Public License. All rights reserved.
// </copyright>
// <author name="Justin Wallace Saunders" email="justinsa@live.ca" />
//-----------------------------------------------------------------------------
namespace Community.Tools.Plugins
{
    using System;

    /// <summary>
    /// Defines a base class for an IPlugin that can host other IPlugins.
    /// </summary>
    public abstract class PluginHost : Plugin
    {
        /// <summary>
        /// Initializes a new instance of the PluginHost class.
        /// </summary>
        /// <param name="name">The plugin name</param>
        protected PluginHost(string name) : base(name)
        {
            this.PluginManager = new PluginManager();
            this.PluginManager.PluginLoadedEvent += new EventHandler<PluginLoadedEventArgs>(this.PluginLoadedEventHandler);
            this.PluginManager.PluginUnloadedEvent += new EventHandler<PluginUnloadedEventArgs>(this.PluginUnloadedEventHandler);
        }

        /// <summary>
        /// Gets or sets the collection of plugins this host contains.
        /// </summary>
        protected PluginManager PluginManager { get; set; }

        /// <summary>
        /// Loads all plugins from the selected path matching this hosts criteria.
        /// </summary>
        /// <param name="path">The directory or file path to request</param>
        public void Load(string path)
        {
            this.PluginManager.Load(path, false);
        }

        /// <summary>
        /// Unloads the plugin related to the <paramref name="key"/>.
        /// </summary>
        /// <param name="key">The key of the plugin to unload</param>
        public void Unload(string key)
        {
            this.PluginManager.Unload(key);
        }

        /// <summary>
        /// Implemented by an inheriting class to handle actions that should be
        /// performed when a plugin has been loaded by the host.
        /// </summary>
        /// <param name="plugin">The loaded Plugin</param>
        protected abstract void PluginLoaded(IPlugin plugin);

        /// <summary>
        /// Implemented by an inheriting class to handle actions that should be
        /// performed when a plugin has been unloaded by the host.
        /// </summary>
        /// <param name="plugin">The unloaded Plugin</param>
        protected abstract void PluginUnloaded(IPlugin plugin);

        /// <summary>
        /// The plugin loaded event handler is raised when a plugin is loaded.
        /// </summary>
        /// <param name="sender">The sender</param>
        /// <param name="e">The event arguments</param>
        private void PluginLoadedEventHandler(object sender, PluginLoadedEventArgs e)
        {
            if (e != null && e.Plugin != null)
            {
                this.PluginLoaded(e.Plugin);
            }
        }

        /// <summary>
        /// The plugin unloaded event handler is raised when a plugin is unloaded.
        /// </summary>
        /// <param name="sender">The sender</param>
        /// <param name="e">The event arguments</param>
        private void PluginUnloadedEventHandler(object sender, PluginUnloadedEventArgs e)
        {
            if (e != null && e.Plugin != null)
            {
                this.PluginUnloaded(e.Plugin);
            }
        }
    }
}
